package com.example.bourse.core.utils;

import org.noear.solon.core.handle.Context;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * SSE（Server-Sent Events）工具类
 * 
 * <p>用于管理SSE连接和事件发送，支持以下功能：</p>
 * <ul>
 *   <li>多客户端连接管理</li>
 *   <li>事件广播</li>
 *   <li>指定客户端事件发送</li>
 *   <li>自动连接关闭检测</li>
 *   <li>资源清理</li>
 * </ul>
 * 
 * <p>使用示例：</p>
 * <pre>
 * // 注册客户端
 * SseUtil.registerClient(ctx);
 * 
 * // 发送事件
 * SseUtil.broadcast("Hello World");
 * 
 * // 关闭连接
 * SseUtil.closeAll();
 * </pre>
 */
public class SseUtil {
    private static final Map<String, Context> clients = new ConcurrentHashMap<>();
    private static final AtomicInteger clientCounter = new AtomicInteger(0);

    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    /**
     * 注册SSE客户端
     * @param ctx 请求上下文
     * @param clientId 前端传入的唯一客户端ID
     */
    /**
     * 注册SSE客户端
     * @param ctx 请求上下文
     * @param clientId 前端传入的唯一客户端ID
     * @return 是否注册成功
     */
    public static boolean registerClient(Context ctx, String clientId) {
        synchronized (clients) {
            // 检查ID是否已存在
            if (clients.containsKey(clientId)) {
                return false;
            }
            
            // 注册新客户端
            clients.put(clientId, ctx);
            
            // 设置SSE响应头
            ctx.contentType("text/event-stream");
            ctx.headerSet("Cache-Control", "no-cache");
            ctx.headerSet("Connection", "keep-alive");
            
            // 启动心跳检测
            scheduler.scheduleAtFixedRate(() -> {
                try {
                    if (!sendHeartbeat(clientId)) {
                        clients.remove(clientId);
                    }
                } catch (Exception e) {
                    clients.remove(clientId);
                }
            }, 10, 10, TimeUnit.SECONDS);
            
            // 发送初始事件
            try {
                sendEvent(clientId, "Welcome to SSE!");
                return true;
            } catch (Exception e) {
                clients.remove(clientId);
                throw new RuntimeException("Failed to register SSE client", e);
            }
        }
    }

    /**
     * 检查客户端是否连接
     * @param clientId 客户端ID
     * @return 是否连接
     */
    public static boolean isClientConnected(String clientId) {
        synchronized (clients) {
            Context ctx = clients.get(clientId);
            if (ctx == null) {
                return false;
            }
            
            try {
                // 发送心跳包测试连接
                ctx.output(":ping\n\n");
                ctx.flush();
                return true;
            } catch (IOException e) {
                clients.remove(clientId);
                return false;
            }
        }
    }

    /**
     * 验证客户端ID是否有效
     * @param clientId 客户端ID
     * @return 是否有效
     */
    public static boolean isValidClientId(String clientId) {
        return clientId != null && !clientId.trim().isEmpty();
    }

    private static boolean sendHeartbeat(String clientId) {
        Context ctx = clients.get(clientId);
        if (ctx != null) {
            synchronized (ctx) {
                try {
                    ctx.output(":heartbeat\n\n");
                    ctx.flush();
                    return true;
                } catch (IOException e) {
                    return false;
                }
            }
        }
        return false;
    }

    public static void sendEvent(String clientId, String data) {
        Context ctx = clients.get(clientId);
        if (ctx != null) {
            synchronized (ctx) {
                try {
                    // 发送心跳包测试连接
                    ctx.output(":ping\n\n");
                    ctx.flush();
                    
                    // 发送实际数据
                    String event = "data: " + data + "\n\n";
                    ctx.output(event);
                    ctx.flush();
                } catch (IOException e) {
                    // 连接已关闭
                    clients.remove(clientId);
                }
            }
        }
    }

    /**
     * 向所有连接的客户端广播事件
     * 
     * @param data 要广播的事件数据
     */
    public static void broadcast(String data) {
        clients.forEach((clientId, ctx) -> {
            synchronized (ctx) {
                try {
                    // 发送心跳包测试连接
                    ctx.output(":ping\n\n");
                    ctx.flush();
                    
                    // 发送实际数据
                    String event = "data: " + data + "\n\n";
                    ctx.output(event);
                    ctx.flush();
                } catch (IOException e) {
                    // 连接已关闭
                    clients.remove(clientId);
                }
            }
        });
    }

    /**
     * 关闭指定客户端的SSE连接
     * 
     * @param clientId 要关闭的客户端ID
     */
    public static void closeClient(String clientId) {
        Context ctx = clients.remove(clientId);
        if (ctx != null) {
            try {
                ctx.output("event: close\ndata: {}\n\n");
                ctx.flush();
            } catch (IOException e) {
                // 连接已关闭，直接清理
                clients.remove(clientId);
            }
        }
    }

    /**
     * 关闭所有SSE连接并清理资源
     */
    public static void closeAll() {
        // 创建线程安全的迭代器
        Iterator<Map.Entry<String, Context>> iterator = clients.entrySet().iterator();
        
        while (iterator.hasNext()) {
            Map.Entry<String, Context> entry = iterator.next();
            String clientId = entry.getKey();
            Context ctx = entry.getValue();
            
            // 对每个客户端进行独立同步处理
            synchronized (ctx) {
                try {
                    // 检查连接是否仍然有效
                    try {
                        ctx.output(":ping\n\n");
                        ctx.flush();
                    } catch (IOException e) {
                        // 连接已关闭
                        iterator.remove();
                        continue;
                    }
                    
                    // 发送关闭事件
                    ctx.output("event: close\ndata: {}\n\n");
                    ctx.flush();
                    
                    // 关闭连接
                    ctx.close();
                } catch (IOException e) {
                    // 连接已关闭，直接移除
                } finally {
                    // 确保从集合中移除
                    iterator.remove();
                }
            }
        }
    }
}
